#include "baidu-ai-asr.h"
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <curl/curl.h>
#include <fstream>
#include <memory>
#include "json/json.h"

BaiduAiAsr::BaiduAiAsr(const string &appKey, const string &secretKey)
{
    mAppKey = appKey;
    mSecretKey = secretKey;
}

inline size_t onWriteData(void *buffer, size_t size, size_t nmemb, void *userp)
{
    std::string *str = dynamic_cast<std::string *>((std::string *)userp);
    str->append((char *)buffer, size * nmemb);
    return nmemb;
}

/**
 * 获取token
 */
string BaiduAiAsr::getAccessToken()
{
    std::string result;
    CURL *curl;
    CURLcode res;
    curl = curl_easy_init();
    if (curl)
    {
        curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
        string url = "https://aip.baidubce.com/oauth/2.0/token?client_id=" + mAppKey + "&client_secret=" + mSecretKey + "&grant_type=client_credentials";
        cout << "request url :" << url << endl;
        curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
        curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
        curl_easy_setopt(curl, CURLOPT_DEFAULT_PROTOCOL, "undefined");
        struct curl_slist *headers = NULL;
        headers = curl_slist_append(headers, "Content-Type: application/json");
        headers = curl_slist_append(headers, "Accept: application/json");
        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
        const char *data = "";
        curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &result);
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, onWriteData);
        res = curl_easy_perform(curl);
    }
    curl_easy_cleanup(curl);
    // cout << result << endl;
    return pareJsonToken(result);
}

string BaiduAiAsr::pareJsonToken(const string &jsonData)
{
    Json::Reader reader;
    Json::Value root;
    bool ok = reader.parse(jsonData, root);
    if (!ok)
    {
        return string();
    }
    return root["access_token"].asString();
}

string BaiduAiAsr::parseJonsToAudioText(const string &jsonData)
{
    Json::Reader reader;
    Json::Value root;
    bool ok = reader.parse(jsonData, root);
    if (!ok)
    {
        return string();
    }
    // cout << jsonData << endl;
    return root["result"][0].asString();
}

string BaiduAiAsr::asrAudioData(const string &token, const vector<uint8_t> &audio)
{
    std::string result;
    CURL *curl;
    CURLcode res;
    curl = curl_easy_init();
    if (curl)
    {
        curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
        string url = "http://vop.baidu.com/server_api?dev_pid=1537&cuid=1234567C&token=" + token;
        cout << "request url :" << url << endl;
        curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
        curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
        curl_easy_setopt(curl, CURLOPT_DEFAULT_PROTOCOL, "undefined");
        struct curl_slist *headers = NULL;
        headers = curl_slist_append(headers, "Content-Type: audio/pcm;rate=16000");
        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
        curl_easy_setopt(curl, CURLOPT_POSTFIELDS, audio.data());
        curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, audio.size());
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &result);
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, onWriteData);
        res = curl_easy_perform(curl);
        curl_slist_free_all(headers);
    }
    curl_easy_cleanup(curl);

    if (res != CURLE_OK)
    {
        // curl 失败
        fprintf(stderr, "perform curl error: %s.\n", curl_easy_strerror(res));
        return string();
    }
    // cout << result << endl;
    return parseJonsToAudioText(result);
}
